/*******************************************************************************
 * Copyright (c) 2023-07-19 @author <a href="mailto:iffiff1@gmail.com">Tyler Chen</a>.
 * All rights reserved.
 *
 * Contributors:
 *     <a href="mailto:iffiff1@gmail.com">Tyler Chen</a> - initial API and implementation.
 ******************************************************************************/
package org.iff.base;

import org.apache.commons.lang3.StringUtils;
import org.iff.util.PreRequired;
import org.iff.util.Utils;

import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

/**
 * BaseUtil， 不使用 interface 因为会把这些工具类方法暴露出去
 *
 * @author <a href="mailto:iffiff1@gmail.com">Tyler Chen</a>
 * @since 2023-07-19
 */
public abstract class BaseUtil {

    /**
     * Is Null or Blank
     */
    protected boolean nob(Object obj) {
        return Utils.isNullOrBlank(obj);
    }

    /**
     * Is Not Null or Blank
     */
    protected boolean nnob(Object obj) {
        return Utils.isNotNullOrBlank(obj);
    }

    /**
     * Is has any empty object
     */
    protected boolean anyEmpty(Object... objs) {
        return Utils.anyEmpty(objs);
    }

    /**
     * Is all empty object
     */
    protected boolean allEmpty(Object... objs) {
        return Utils.allEmpty(objs);
    }

    /**
     * 日期的起始时间，如：2022-01-01 00:00:00.000
     */
    protected Date dayStart(Date date) {
        return Utils.dayStartAndEnd(date).getLeft();
    }

    /**
     * 日期的结束时间，如：2022-01-01 23:59:59.999
     */
    protected Date dayEnd(Date date) {
        return Utils.dayStartAndEnd(date).getRight();
    }

    /**
     * requireNotNull
     */
    protected <T> T rnn(T t) {
        return PreRequired.requireNotNull(t);
    }

    /**
     * requireNotNull
     */
    protected <T> T rnn(T t, String errMsg, Object... args) {
        return PreRequired.requireNotNull(t, errMsg, args);
    }

    /**
     * requireNull
     */
    protected <T> T rNull(T t, String errMsg, Object... args) {
        return PreRequired.requireNull(t, errMsg, args);
    }

    /**
     * require True
     */
    protected <T> T rTrue(T expression, String errMsg, Object... args) {
        return PreRequired.requireTrue(expression, errMsg, args);
    }

    /**
     * requireNotBlank
     */
    protected <T> T rnb(T t, String errMsg, Object... args) {
        PreRequired.requireTrue(nnob(t), errMsg, args);
        return t;
    }

    protected <T> T copy(Object src, T target) {
        return Utils.copy(src, target);
    }

    protected <T> List<T> toList(T... values) {
        return Utils.toList(values);
    }

    protected <T> List<T> toList(Set<T> set) {
        return new ArrayList<>(safeSet(set));
    }

    protected <T> Set<T> toSet(T... values) {
        return new LinkedHashSet<>(Utils.toList(values));
    }

    protected <T> Set<T> toSet(List<T> list) {
        return new HashSet<>(safeList(list));
    }

    protected Map<?, ?> toMap(Object... keyValues) {
        return Utils.toMap(keyValues);
    }

    protected <T> T optional(T t, Supplier<T> supplier) {
        return t != null ? t : supplier.get();
    }

    protected <T> T optional(T t, T protectedValue) {
        return t != null ? t : protectedValue;
    }

    protected <T> T caseTrue(boolean condition, T trueValue, T falseValue) {
        return condition ? trueValue : falseValue;
    }

    protected <T> T caseFalse(boolean condition, T falseValue, T trueValue) {
        return condition ? falseValue : trueValue;
    }

    protected <T> T caseNob(Object condition, T trueValue, T falseValue) {
        return nob(condition) ? trueValue : falseValue;
    }

    protected <T> T caseNnob(Object condition, T trueValue, T falseValue) {
        return nnob(condition) ? trueValue : falseValue;
    }

    protected <T> List<T> safeList(List<T> list) {
        return Utils.nullToEmptyList(list);
    }

    protected <T> Set<T> safeSet(Set<T> set) {
        return Utils.nullToEmptySet(set);
    }

    protected <K, V> Map<K, V> safeMap(Map<K, V> map) {
        return Utils.nullToEmptyMap(map);
    }

    protected String safeStr(String s) {
        return s == null ? "" : s;
    }

    protected <T> T safeGet(List<T> list, int index) {
        if (list != null && list.size() > index) {
            return list.get(index);
        }
        return null;
    }

    protected <T> T safeGet(T[] array, int index) {
        if (array != null && array.length > index) {
            return array[index];
        }
        return null;
    }

    protected <T, R> List<R> collect(Collection<T> list, Function<T, R> function) {
        return Utils.collect(list, function);
    }

    protected <T, R> List<R> collect(Collection<T> list, Function<T, R> function, Predicate<R> predicate) {
        return Utils.collect(list, function, predicate);
    }

    protected <T, R> Set<R> collectSet(Collection<T> list, Function<T, R> function) {
        return Utils.collectSet(list, function);
    }

    protected <T, R> Set<R> collectSet(Collection<T> list, Function<T, R> function, Predicate<R> predicate) {
        return Utils.collectSet(list, function, predicate);
    }

    protected <T, R> List<R> collectNotNull(Collection<T> list, Function<T, R> function) {
        return Utils.collectNotNull(list, function);
    }

    protected <T, R> Set<R> collectNotNullSet(Collection<T> list, Function<T, R> function) {
        return Utils.collectNotNullSet(list, function);
    }

    protected <T, R> Map<R, T> collectMap(Collection<T> list, Function<T, R> function) {
        return Utils.collectMap(list, function);
    }

    protected <T, R> Map<R, T> collectMap(Collection<T> list, Function<T, R> function, Predicate<T> predicate) {
        return Utils.collectMap(list, function, predicate);
    }

    protected <T, R> Map<R, List<T>> collectMapList(Collection<T> list, Function<T, R> function) {
        return Utils.collectMapList(list, function);
    }

    protected <T> List<T> filter(Collection<T> list, Predicate<T> predicate) {
        return Utils.filter(list, predicate);
    }

    protected <T> T first(Collection<T> list, Predicate<T> predicate) {
        return Utils.first(list, predicate);
    }

    protected <T> T protectedBlank(Object toTest, T value, T protectedValue) {
        return Utils.isNullOrBlank(toTest) ? protectedValue : value;
    }

    protected String protectedStr(String str, String protectedValue) {
        return blankStr(str) ? protectedValue : str;
    }

    protected String protectedStr(String str, Supplier<String> supplier) {
        return blankStr(str) ? supplier.get() : str;
    }

    protected Long toLong(String value, Long defaultValue) {
        return Utils.toLong(value, defaultValue);
    }

    protected Long toLong(String value) {
        return Utils.toLong(value);
    }

    protected Integer toInt(String value, Integer defaultValue) {
        return Utils.toInt(value, defaultValue);
    }

    protected Integer toInt(String value) {
        return Utils.toInt(value);
    }

    protected boolean sameAs(Object a, Object b) {
        return Objects.equals(a, b);
    }

    protected boolean blankStr(String str) {
        return StringUtils.isBlank(str);
    }

    /**
     * @return true: can not use like; false: can use like
     */
    protected boolean noLike(String condition) {
        return blankStr(condition) || !StringUtils.contains(condition, '%');
    }

    /**
     * @return true: can not use eq; false: can use eq
     */
    protected boolean noEqual(String condition) {
        return blankStr(condition) || StringUtils.contains(condition, '%');
    }

    protected String toLike(String condition) {
        return blankStr(condition) ? null : ("%" + condition.trim() + "%");
    }
}
